namespace SubSonic
{
    using Microsoft.CSharp;
    using SubSonic.Utilities;
    using System;
    using System.CodeDom.Compiler;
    using System.Data;

    public class CSharpCodeLanguage : ICodeLanguage
    {
        private readonly string[] keywords = new string[] { 
            "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "date", "datetime", "decimal", 
            "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", 
            "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", 
            "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", 
            "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "volatile", "void", "while", "get", 
            "partial", "set", "value", "where", "yield"
         };

        public CodeDomProvider CreateCodeProvider()
        {
            return new CSharpCodeProvider();
        }

        private static string GetDefaultValue(string colName, DbType dbType)
        {
            if (Utility.IsLogicalDeleteColumn(colName))
            {
                return "false";
            }
            switch (dbType)
            {
                case DbType.AnsiString:
                case DbType.String:
                case DbType.AnsiStringFixedLength:
                case DbType.StringFixedLength:
                    return "null";

                case DbType.Binary:
                    return "null";

                case DbType.Boolean:
                    return "false";

                case DbType.Date:
                case DbType.DateTime:
                    return "new DateTime(1900,01, 01)";

                case DbType.Guid:
                    return "Guid.Empty";

                case DbType.Xml:
                    return "";
            }
            return "0";
        }

        public string GetDefaultValue(string colName, DbType dbType, bool isNullableColumn)
        {
            string defaultValue = GetDefaultValue(colName, dbType);
            if (isNullableColumn && Utility.IsNullableDbType(dbType))
            {
                defaultValue = defaultValue + "?";
            }
            return defaultValue;
        }

        public string GetUsingStatements(string[] namespaces)
        {
            string str = "";
            foreach (string str2 in namespaces)
            {
                string str3 = str;
                str = str3 + "using " + str2 + ";" + Environment.NewLine;
            }
            return str;
        }

        private static string GetVariableType(DbType dbType)
        {
            switch (dbType)
            {
                case DbType.AnsiString:
                case DbType.String:
                case DbType.AnsiStringFixedLength:
                case DbType.StringFixedLength:
                    return "string";

                case DbType.Binary:
                    return "byte[]";

                case DbType.Byte:
                    return "byte";

                case DbType.Boolean:
                    return "bool";

                case DbType.Currency:
                case DbType.Decimal:
                case DbType.VarNumeric:
                    return "decimal";

                case DbType.Date:
                case DbType.DateTime:
                    return "DateTime";

                case DbType.Double:
                    return "double";

                case DbType.Guid:
                    return "Guid";

                case DbType.Int16:
                    return "short";

                case DbType.Int32:
                    return "int";

                case DbType.Int64:
                    return "long";

                case DbType.Object:
                    return "object";

                case DbType.SByte:
                    return "sbyte";

                case DbType.Single:
                    return "float";

                case DbType.Time:
                    return "TimeSpan";

                case DbType.UInt16:
                    return "ushort";

                case DbType.UInt32:
                    return "uint";

                case DbType.UInt64:
                    return "ulong";
            }
            return "string";
        }

        public string GetVariableType(DbType dbType, bool isNullableColumn)
        {
            string variableType = GetVariableType(dbType);
            if (isNullableColumn && Utility.IsNullableDbType(dbType))
            {
                variableType = variableType + "?";
            }
            return variableType;
        }

        public bool IsKeyword(string word)
        {
            return (Array.IndexOf<string>(this.keywords, word.ToLower()) != -1);
        }

        public string CodeProvider
        {
            get
            {
                return "CSharpCodeProvider";
            }
        }

        public string DefaultUsingStatements
        {
            get
            {
                return "using System; \r\nusing System.Text; \r\nusing System.Data;\r\nusing System.Data.SqlClient;\r\nusing System.Data.Common;\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing System.ComponentModel;\r\nusing System.Configuration; \r\nusing System.Xml; \r\nusing System.Xml.Serialization;\r\nusing SubSonic; \r\nusing SubSonic.Utilities;\r\n";
            }
        }

        public string FileExtension
        {
            get
            {
                return ".cs";
            }
        }

        public string Identifier
        {
            get
            {
                return "C#";
            }
        }

        public string ShortName
        {
            get
            {
                return "cs";
            }
        }

        public string TemplatePrefix
        {
            get
            {
                return "CS_";
            }
        }
    }
}

